/*
* Copyright 2010 Pavel Kozhin 
*
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed  under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License.
*
* Author: Pavel Kozhin.
*/

package org.etherframework.behaviour.rules
{
	import org.etherframework.core.ether_internal;
	import org.etherframework.behaviour.rules.core.Descriptor;
	
	import flash.events.IEventDispatcher;
	import flash.utils.describeType;
	
	import mx.core.mx_internal;
	
	use namespace mx_internal;
	use namespace ether_internal;
	
	import mx.core.IMXMLObject;
	import org.etherframework.behaviour.rules.core.IChild;
	import flash.utils.Dictionary;
	import org.etherframework.behaviour.rules.core.IControl;
	import flash.events.Event;
	import org.etherframework.behaviour.rules.context.IContext;
	import org.etherframework.behaviour.rules.core.Control;
	import org.etherframework.behaviour.rules.util.DescriptorParser;
	import org.etherframework.behaviour.rules.util.ContextResolver;
	
	[Event(name="ready", type="flash.events.Event")]
	
	public class Rules extends Control implements IRules
	{
		private var document:Object;
		
		private var inited:Boolean = false;
		
		ether_internal var children:Array = [];
		
		public function initialized(document:Object, id:String):void
		{
			this.id = id;
			this.document = document;
			descriptor = new Descriptor(id, 0, null, null, null, describeType(this));
		}
		
		override public function initialize():void
		{
			if (!(dispatcher || document || !inited))
				return;
			
			inited = true;
			ContextResolver.register(this, function(value:IContext):void {_context = value;},
										   function(value:IContext):void {_lastContext = value;},
										   function(value:IContext):void {_localContext = value;},
										   function(value:*):void {_reason = value;});
			
			var handler:IRule;
			var map:Dictionary = DescriptorParser.execute(this, descriptor.type);
			ContextResolver.enableBindingsByObject(this, descriptor.type, false);
				
			for (var member:Object in map)
			{
				if ((member is IRule) && !IRule(member).descriptor.parent)
				{
					handler = member as IRule;
					children.push(member);
					handler.descriptor.owner = this;
					handler.descriptor.document = this;
					handler.dispatcher = _dispatcher;
					handler.initialize();
				}
			}
		}
		
		private var _dispatcher:IEventDispatcher;
		
		public function get dispatcher():IEventDispatcher
		{
			return _dispatcher;
		}
		
		public function set dispatcher(value:IEventDispatcher):void
		{
			_dispatcher = value;
		}
		
		private var _preventPropagation:Boolean = true;

		[Inspectable(defaultValue="true")]
		public function get preventPropagation():Boolean
		{
			return _preventPropagation;
		}

		public function set preventPropagation(value:Boolean):void
		{
			_preventPropagation = value;
		}
		
		private var _context:IContext;
		
		[Bindable(event="propertyChange")]
		override public function get context():IContext
		{
			return _context;
		}
		
		private var _localContext:IContext;

		[Bindable(event="propertyChange")]
		public function get localContext():IContext
		{
			return _localContext;
		}
		
		private var _lastContext:IContext;
		
		[Bindable(event="propertyChange")]
		public function get lastContext():IContext
		{
			return _lastContext;
		}
		
		private var _reason:*;
		
		[Bindable(event="propertyChange")]
		public function get reason():*
		{
			return _reason;
		}
		
		private var _access:String = "local";
		
		[Inspectable(defaultValue="local", enumeration="local,hierarchical,@hierarchical,hierarchical@,global")]
		public function get access():String
		{
			return _access;
		}
		
		public function set access(value:String):void
		{
			_access = value;
		}
		
		private var _domain:String = "single";
		
		[Inspectable(defaultValue="single", enumeration="single,multiple")]
		public function get domain():String
		{
			return _domain;
		}
		
		public function set domain(value:String):void
		{
			_domain = value;
		}
		
	}
}
